001 /*
002 * Copyright 2004 Niclas Hedhman
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package net.dpml.util;
019
020 import java.util.Enumeration;
021 import java.util.Properties;
022 import java.util.Stack;
023 import java.util.StringTokenizer;
024
025 import net.dpml.transit.Transit;
026
027 /**
028 * Utility class that handles substitution of property names in the string
029 * for ${value} relative to a supplied set of properties.
030 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
031 * @version 1.0.2
032 */
033 public final class PropertyResolver
034 {
035 // ------------------------------------------------------------------------
036 // static
037 // ------------------------------------------------------------------------
038
039 static
040 {
041 Object xx = Transit.DPML_DATA;
042 }
043
044 /**
045 * System property symbol substitution from properties.
046 * Replace any occurances of ${[key]} with the value of the property
047 * assigned to the [key] in the system properties.
048 * @param value a string containing possibly multiple ${[value]} sequences
049 * @return the expanded string
050 */
051 public static String resolve( String value )
052 {
053 Properties properties = System.getProperties();
054 return resolve( properties, value );
055 }
056
057 /**
058 * System property symbol substitution from properties.
059 * Replace any occurances of ${[key]} with the value of the property
060 * assigned to the [key] in the system properties or supplied properties.
061 * @param properties an arbitary properties file containing unresolved properties
062 * @return the property file with expended properties
063 */
064 public static Properties resolve( Properties properties )
065 {
066 Properties system = System.getProperties();
067 Enumeration names = properties.propertyNames();
068 while( names.hasMoreElements() )
069 {
070 String name = (String) names.nextElement();
071 String old = properties.getProperty( name );
072 String value = resolve( old );
073 String v2 = resolve( properties, value );
074 if( !v2.equals( old ) )
075 {
076 properties.setProperty( name, v2 );
077 }
078 }
079 return properties;
080 }
081
082 /**
083 * Symbol substitution from properties.
084 * Replace any occurances of ${[key]} with the value of the property
085 * assigned to the [key] in the supplied properties argument.
086 * @param props the source properties from which substitution is resolved
087 * @param value a string containing possibly multiple ${[value]} sequences
088 * @return the expanded string
089 */
090 public static String resolve( Properties props, String value )
091 {
092 if( value == null )
093 {
094 return null;
095 }
096
097 // optimization for common case.
098 if( value.indexOf( '$' ) < 0 )
099 {
100 return value;
101 }
102 int pos1 = value.indexOf( "${" );
103 if( pos1 < 0 )
104 {
105 return value;
106 }
107
108 Stack stack = new Stack();
109 StringTokenizer st = new StringTokenizer( value, "${}", true );
110
111 while ( st.hasMoreTokens() )
112 {
113 String token = st.nextToken();
114
115 if( token.equals( "}" ) )
116 {
117 String name = (String) stack.pop();
118 String open = (String) stack.pop();
119 if( open.equals( "${" ) )
120 {
121 String propValue = System.getProperty( name );
122 if( propValue == null )
123 {
124 propValue = props.getProperty( name );
125 }
126 if( propValue == null )
127 {
128 push( stack, "${" + name + "}" );
129 }
130 else
131 {
132 push( stack, propValue );
133 }
134 }
135 else
136 {
137 push( stack, "${" + name + "}" );
138 }
139 }
140 else
141 {
142 if( token.equals( "$" ) )
143 {
144 stack.push( "$" );
145 }
146 else
147 {
148 push( stack, token );
149 }
150 }
151 }
152 String result = "";
153 while ( stack.size() > 0 )
154 {
155 result = stack.pop() + result;
156 }
157 return result;
158 }
159
160 /**
161 * Pushes a value on a stack
162 * @param stack the stack
163 * @param value the value
164 */
165 private static void push( Stack stack , String value )
166 {
167 if( stack.size() > 0 )
168 {
169 String data = (String) stack.pop();
170 if( data.equals( "${" ) )
171 {
172 stack.push( data );
173 stack.push( value );
174 }
175 else
176 {
177 stack.push( data + value );
178 }
179 }
180 else
181 {
182 stack.push( value );
183 }
184 }
185
186 // ------------------------------------------------------------------------
187 // constructor
188 // ------------------------------------------------------------------------
189
190 /**
191 * Null constructor.
192 */
193 private PropertyResolver()
194 {
195 }
196 }
197